# 报价系统仪表盘首页
<script setup lang="ts">
// 导入必要的组件和图标
import { ref } from 'vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart, PieChart } from 'echarts/charts'
import {
  GridComponent,
  TooltipComponent,
  LegendComponent,
  TitleComponent,
} from 'echarts/components'
import VChart from 'vue-echarts'
import {
  Money,
  Document,
  List,
  SetUp,
  QuestionFilled,
  ArrowUp,
  ArrowDown,
} from '@element-plus/icons-vue'

// 注册必须的组件
use([
  CanvasRenderer,
  LineChart,
  PieChart,
  GridComponent,
  TooltipComponent,
  LegendComponent,
  TitleComponent,
])

// 获取状态对应的类型
const getStatusType = (status: string): string => {
  const typeMap: Record<string, string> = {
    草稿: 'info',
    已提交: 'warning',
    已确认: 'success',
  }
  return typeMap[status] || 'info'
}

// 统计数据
const statisticsData = [
  {
    title: '本月报价单',
    value: '126',
    icon: Document,
    bgColor: '#409EFF',
    trend: 'up',
    rate: '15.2',
    tip: '本月累计报价单数量',
  },
  {
    title: '本月报价金额',
    value: '¥3,256,800',
    icon: Money,
    bgColor: '#67C23A',
    trend: 'up',
    rate: '8.5',
    tip: '本月报价单总金额',
  },
  {
    title: 'BOM总数',
    value: '358',
    icon: List,
    bgColor: '#E6A23C',
    trend: 'up',
    rate: '5.3',
    tip: '系统中的BOM总数量',
  },
  {
    title: '物料总数',
    value: '1,286',
    icon: SetUp,
    bgColor: '#909399',
    trend: 'up',
    rate: '3.2',
    tip: '系统中的物料总数量',
  },
]

// 时间范围
const timeRange = ref('month')

// 报价趋势图配置
const lineChartOption = {
  tooltip: {
    trigger: 'axis',
  },
  legend: {
    data: ['报价金额', '报价数量'],
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true,
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月'],
  },
  yAxis: [
    {
      type: 'value',
      name: '金额(万)',
      position: 'left',
    },
    {
      type: 'value',
      name: '数量',
      position: 'right',
    },
  ],
  series: [
    {
      name: '报价金额',
      type: 'line',
      smooth: true,
      yAxisIndex: 0,
      data: [320, 280, 350, 420, 390, 380, 450],
      itemStyle: { color: '#409EFF' },
    },
    {
      name: '报价数量',
      type: 'line',
      smooth: true,
      yAxisIndex: 1,
      data: [15, 12, 18, 20, 16, 18, 22],
      itemStyle: { color: '#67C23A' },
    },
  ],
}

// BOM物料构成分析
const pieChartOption = {
  tooltip: {
    trigger: 'item',
  },
  legend: {
    orient: 'vertical',
    left: 'left',
  },
  series: [
    {
      name: '物料类型',
      type: 'pie',
      radius: '50%',
      data: [
        { value: 485, name: '原材料' },
        { value: 320, name: '半成品' },
        { value: 234, name: '成品' },
        { value: 158, name: '辅料' },
        { value: 89, name: '包装材料' },
      ],
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)',
        },
      },
    },
  ],
}

// 最近报价记录
const recentQuotes = [
  {
    quoteNo: 'QT20240319001',
    title: '机械零件报价',
    amount: 156800,
    createTime: '2024-03-19 14:23',
    status: '已确认',
  },
  {
    quoteNo: 'QT20240319002',
    title: '电子元件报价',
    amount: 89500,
    createTime: '2024-03-19 11:35',
    status: '已提交',
  },
  {
    quoteNo: 'QT20240318003',
    title: '包装材料报价',
    amount: 45600,
    createTime: '2024-03-18 16:42',
    status: '草稿',
  },
  {
    quoteNo: 'QT20240318002',
    title: '五金配件报价',
    amount: 78900,
    createTime: '2024-03-18 15:20',
    status: '已确认',
  },
]

// 待办事项
const todoList = [
  {
    content: '新增报价单待审核',
    time: '10分钟前',
    type: 'warning',
    color: '#E6A23C',
  },
  {
    content: 'BOM成本更新提醒',
    time: '30分钟前',
    type: 'danger',
    color: '#F56C6C',
  },
  {
    content: '物料价格变动提醒',
    time: '2小时前',
    type: 'info',
    color: '#909399',
  },
  {
    content: '报价单即将过期',
    time: '4小时前',
    type: 'primary',
    color: '#409EFF',
  },
]

// 定义页面动画持续时间变量
const ANIMATION_DURATION = '0.3s'
</script>

<template>
  <div class="dashboard-container">
    <!-- 数据概览卡片 -->
    <el-row :gutter="20">
      <el-col :span="6"
              v-for="(item, index) in statisticsData"
              :key="index">
        <el-card class="statistics-card"
                 :body-style="{ padding: '20px' }">
          <div class="card-header">
            <div class="card-title">
              <span>{{ item.title }}</span>
              <el-tooltip :content="item.tip"
                          placement="top">
                <el-icon>
                  <QuestionFilled />
                </el-icon>
              </el-tooltip>
            </div>
            <div class="card-icon"
                 :style="{ background: item.bgColor }">
              <el-icon>
                <component :is="item.icon" />
              </el-icon>
            </div>
          </div>
          <div class="card-content">
            <div class="number">{{ item.value }}</div>
            <div class="compare">
              <span :class="item.trend === 'up' ? 'up' : 'down'">
                <el-icon>
                  <component :is="item.trend === 'up' ? 'ArrowUp' : 'ArrowDown'" />
                </el-icon>
                {{ item.rate }}%
              </span>
              较上月
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 报价记录和待办事项 -->
    <el-row :gutter="20"
            class="monitor-row">
      <el-col :span="12">
        <el-card class="monitor-card">
          <template #header>
            <div class="monitor-header">
              <span>最近报价记录</span>
              <el-button type="primary"
                         link>查看更多</el-button>
            </div>
          </template>
          <el-table :data="recentQuotes"
                    style="width: 100%"
                    max-height="400">
            <el-table-column prop="quoteNo"
                             label="报价单号"
                             width="140" />
            <el-table-column prop="title"
                             label="报价标题"
                             min-width="120" />
            <el-table-column prop="amount"
                             label="金额"
                             width="120">
              <template #default="{ row }">
                ¥{{ row.amount.toLocaleString() }}
              </template>
            </el-table-column>
            <el-table-column prop="status"
                             label="状态"
                             width="100">
              <template #default="{ row }">
                <el-tag :type="getStatusType(row.status)">
                  {{ row.status }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>

      <el-col :span="12">
        <el-card class="todo-card">
          <template #header>
            <div class="todo-header">
              <span>待办事项</span>
              <el-button type="primary"
                         link>全部处理</el-button>
            </div>
          </template>
          <el-timeline>
            <el-timeline-item v-for="(item, index) in todoList"
                              :key="index"
                              :type="item.type"
                              :timestamp="item.time"
                              :color="item.color">
              {{ item.content }}
            </el-timeline-item>
          </el-timeline>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<style lang="scss" scoped>
// 定义变量
$animation-duration: 0.3s;
$primary-color: #409eff;
$success-color: #67c23a;
$warning-color: #e6a23c;
$danger-color: #f56c6c;
$info-color: #909399;
$text-primary: #303133;
$text-regular: #606266;
$text-secondary: #909399;
$border-color: #dcdfe6;
$hover-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);

.dashboard-container {
  padding: 20px;
  background: #f0f2f5;
  animation: fade-in 0.5s ease-out;

  .statistics-card {
    margin-bottom: 20px;
    transition: all $animation-duration ease;

    &:hover {
      transform: translateY(-5px);
      box-shadow: $hover-shadow;
    }

    .card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;

      .card-title {
        display: flex;
        align-items: center;
        gap: 8px;
        color: $text-regular;
      }

      .card-icon {
        width: 48px;
        height: 48px;
        border-radius: 8px;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: transform $animation-duration;

        .el-icon {
          font-size: 24px;
          color: #fff;
        }
      }
    }

    .card-content {
      .number {
        font-size: 24px;
        font-weight: bold;
        color: $text-primary;
        margin-bottom: 8px;
      }

      .compare {
        font-size: 13px;
        color: $text-secondary;

        .up {
          color: $success-color;
        }
        .down {
          color: $danger-color;
        }
      }
    }
  }

  .chart-row {
    margin-bottom: 20px;

    .chart-card {
      .chart-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
      }

      .chart-container {
        height: 350px;

        .chart {
          height: 100%;
        }
      }
    }
  }

  .monitor-row {
    .monitor-card,
    .todo-card {
      .monitor-header,
      .todo-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
    }
  }
}

// 动画
@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>
